package com.base.components.common.util;

import com.google.common.collect.Sets;

import java.util.Collection;
import java.util.function.Supplier;

/**
 * CollectionHelper
 *
 * @author <a href="drakelee1221@gmail.com">LiGeng</a>
 * @version v1.0.0
 * @date 2018-07-06 14:07
 */
public abstract class CollectionHelper {

  /**
   * 比较两个集合中是否都含有同一个元素
   * @param c1 -
   * @param c2 -
   * @return boolean
   */
  public static <E> boolean existsSameElement(Collection<E> c1, Collection<E> c2){
    if(c1 != null && c2 != null && !c1.isEmpty() && !c2.isEmpty()){
      if(c1.size() < c2.size()){
        for (E o : c1) {
          if(c2.contains(o)){
            return true;
          }
        }
      }
      else{
        for (E o : c2) {
          if(c1.contains(o)){
            return true;
          }
        }
      }
    }
    return false;
  }

  /**
   * 交集
   * @param c1 -
   * @param c2 -
   * @return LinkedHashSet 新集合
   */
  public static <E> Collection<E> sameElements(Collection<E> c1, Collection<E> c2){
    return sameElements(c1, c2, null);
  }

  /**
   * 交集
   * @param c1 -
   * @param c2 -
   * @param collectionFactory - 集合构造器，如 HashSet::new
   * @return collectionFactory构建的新集合
   */
  public static <E, C extends Collection<E>> Collection<E> sameElements(Collection<E> c1, Collection<E> c2, Supplier<C> collectionFactory){
    Collection<E> left = createCollection(collectionFactory);
    if(c1 != null && c2 != null && !c1.isEmpty() && !c2.isEmpty()){
      Collection<E> that;
      if(c1.size() < c2.size()){
        left.addAll(c1);
        that = c2;
      }
      else{
        left.addAll(c2);
        that = c1;
      }
      left.removeIf(o -> !that.contains(o));
      return left;
    }
    return left;
  }

  /**
   * 交集
   * @param c1 -
   * @param c2 -
   * @return LinkedHashSet 新集合
   */
  public static <E> Collection<E> union(Collection<E> c1, Collection<E> c2){
    return union(c1, c2, null);
  }

  /**
   * 交集
   * @param c1 -
   * @param c2 -
   * @param collectionFactory - 集合构造器，如 HashSet::new
   * @return collectionFactory构造的新集合
   */
  public static <E, C extends Collection<E>> Collection<E> union(Collection<E> c1, Collection<E> c2, Supplier<C> collectionFactory){
    Collection<E> left = createCollection(collectionFactory);
    if(c1 != null && c2 != null && !c1.isEmpty() && !c2.isEmpty()){
      Collection<E> right;
      if(c1.size() < c2.size()){
        left.addAll(c1);
        right = c2;
      }
      else{
        left.addAll(c2);
        right = c1;
      }
      left.addAll(right);
      return left;
    }
    else if(c1 != null){
      left.addAll(c1);
    }
    else if(c2 != null){
      left.addAll(c2);
    }
    return left;
  }


  /**
   * 比较 c1集合 跟 c2集合 的差集（c1中存在的且c2中不存在的）
   * @param c1 -
   * @param c2 -
   * @return LinkedHashSet 新集合
   */
  public static <E> Collection<E> difference(Collection<E> c1, Collection<E> c2){
    return difference(c1, c2, null);
  }

  /**
   * 比较 c1集合 跟 c2集合 的差集（c1中存在的且c2中不存在的）
   * @param c1 -
   * @param c2 -
   * @param collectionFactory - 集合构造器，如 HashSet::new
   * @return collectionFactory构造的新集合
   */
  public static <E, C extends Collection<E>> Collection<E> difference(Collection<E> c1, Collection<E> c2, Supplier<C> collectionFactory){
    Collection<E> left = createCollection(collectionFactory);
    if(c1 != null && c2 != null && !c1.isEmpty() && !c2.isEmpty()){
      left.addAll(c1);
      left.removeAll(c2);
      return left;
    }
    else if(c1 != null){
      left.addAll(c1);
    }
    return left;
  }

  private static <E, C extends Collection<E>> Collection<E> createCollection(Supplier<C> collectionFactory){
    if(collectionFactory == null){
      return Sets.newLinkedHashSet();
    }
    C c = collectionFactory.get();
    if(c == null){
      return Sets.newLinkedHashSet();
    }
    return c;
  }
}
